﻿using System;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;

namespace GeneratedSettings.MultiSite {
	public class Settings {
		
		private static Dictionary<int, Settings> siteSettings = new Dictionary<int, Settings>();
		private static object syncRoot = new object();
		
		public static Settings ForSite(int siteID) {
			Settings result = null;
			lock(syncRoot) {
				if(siteSettings.TryGetValue(siteID, out result)) return result;
				
				result = new Settings(siteID);
				siteSettings.Add(siteID, result);
				return result;
			}
		}
	
		public int SiteID { get; private set; }
		
		public Settings(int siteID) {
			SiteID = siteID;
			LoadSettings();
		}
		
			
		public AppearanceSettings Appearance { get; set; }
		public class AppearanceSettings {
			protected Settings Settings { get; private set; }
			
			public AppearanceSettings() { }
			
			public AppearanceSettings(Settings settings, Dictionary<string, string> loadFrom) {
				Settings = settings;
				LoadSettings(loadFrom);
			}
			
				
		public ColorsSettings Colors { get; set; }
		public class ColorsSettings {
			protected Settings Settings { get; private set; }
			
			public ColorsSettings() { }
			
			public ColorsSettings(Settings settings, Dictionary<string, string> loadFrom) {
				Settings = settings;
				LoadSettings(loadFrom);
			}
			
				
		// ContentBG
		private string _ContentBG;
		private object _lockContentBG = new object();
		public const string ContentBGDefault = @"rgb(255,255,255)";		
		public string ContentBG {
			get {
				lock(_lockContentBG) {
					if(_ContentBG == null) return ContentBGDefault;			
					return _ContentBG;
				}
			}
			set {
				lock(_lockContentBG) {
					_ContentBG = value;
					
					if(Settings != null)
						Settings.SaveSetting("Appearance.Colors.ContentBG", value);
				}
			}
		}
		
		// HeadBG
		private string _HeadBG;
		private object _lockHeadBG = new object();
		public const string HeadBGDefault = @"rgb(231,237,221)";		
		public string HeadBG {
			get {
				lock(_lockHeadBG) {
					if(_HeadBG == null) return HeadBGDefault;			
					return _HeadBG;
				}
			}
			set {
				lock(_lockHeadBG) {
					_HeadBG = value;
					
					if(Settings != null)
						Settings.SaveSetting("Appearance.Colors.HeadBG", value);
				}
			}
		}
		
		// SiteName
		private string _SiteName;
		private object _lockSiteName = new object();
		public const string SiteNameDefault = @"rgb(81,119,20)";		
		public string SiteName {
			get {
				lock(_lockSiteName) {
					if(_SiteName == null) return SiteNameDefault;			
					return _SiteName;
				}
			}
			set {
				lock(_lockSiteName) {
					_SiteName = value;
					
					if(Settings != null)
						Settings.SaveSetting("Appearance.Colors.SiteName", value);
				}
			}
		}
				
			private void LoadSettings(Dictionary<string, string> settings) {
								string val = null;
											
			if(settings.TryGetValue("Appearance.Colors.ContentBG", out val)) {
				try {
					_ContentBG = val;
				} catch { } // ignore invalid values
			}
			
						
			if(settings.TryGetValue("Appearance.Colors.HeadBG", out val)) {
				try {
					_HeadBG = val;
				} catch { } // ignore invalid values
			}
			
						
			if(settings.TryGetValue("Appearance.Colors.SiteName", out val)) {
				try {
					_SiteName = val;
				} catch { } // ignore invalid values
			}
			
						}
			
		}
	
		public LogoSettings Logo { get; set; }
		public class LogoSettings {
			protected Settings Settings { get; private set; }
			
			public LogoSettings() { }
			
			public LogoSettings(Settings settings, Dictionary<string, string> loadFrom) {
				Settings = settings;
				LoadSettings(loadFrom);
			}
			
				
		// Filename
		private string _Filename;
		private object _lockFilename = new object();
				
		public string Filename {
			get {
				lock(_lockFilename) {
								
					return _Filename;
				}
			}
			set {
				lock(_lockFilename) {
					_Filename = value;
					
					if(Settings != null)
						Settings.SaveSetting("Appearance.Logo.Filename", value);
				}
			}
		}
		
		// Width
		private int _Width;
		private object _lockWidth = new object();
				
		public int Width {
			get {
				lock(_lockWidth) {
								
					return _Width;
				}
			}
			set {
				lock(_lockWidth) {
					_Width = value;
					
					if(Settings != null)
						Settings.SaveSetting("Appearance.Logo.Width", value.ToString());
				}
			}
		}
		
		// Height
		private int _Height;
		private object _lockHeight = new object();
				
		public int Height {
			get {
				lock(_lockHeight) {
								
					return _Height;
				}
			}
			set {
				lock(_lockHeight) {
					_Height = value;
					
					if(Settings != null)
						Settings.SaveSetting("Appearance.Logo.Height", value.ToString());
				}
			}
		}
				
			private void LoadSettings(Dictionary<string, string> settings) {
								string val = null;
											
			if(settings.TryGetValue("Appearance.Logo.Filename", out val)) {
				try {
					_Filename = val;
				} catch { } // ignore invalid values
			}
			
						
			if(settings.TryGetValue("Appearance.Logo.Width", out val)) {
				try {
					_Width = int.Parse(val);
				} catch { } // ignore invalid values
			}
			
						
			if(settings.TryGetValue("Appearance.Logo.Height", out val)) {
				try {
					_Height = int.Parse(val);
				} catch { } // ignore invalid values
			}
			
						}
			
		}
			
			private void LoadSettings(Dictionary<string, string> settings) {
								Colors = new ColorsSettings(Settings, settings);
Logo = new LogoSettings(Settings, settings);
			}
			
		}
	
		public AuthenticationSettings Authentication { get; set; }
		public class AuthenticationSettings {
			protected Settings Settings { get; private set; }
			
			public AuthenticationSettings() { }
			
			public AuthenticationSettings(Settings settings, Dictionary<string, string> loadFrom) {
				Settings = settings;
				LoadSettings(loadFrom);
			}
			
				
		public LDAPSettings LDAP { get; set; }
		public class LDAPSettings {
			protected Settings Settings { get; private set; }
			
			public LDAPSettings() { }
			
			public LDAPSettings(Settings settings, Dictionary<string, string> loadFrom) {
				Settings = settings;
				LoadSettings(loadFrom);
			}
			
				
		// Enabled
		private bool _Enabled;
		private object _lockEnabled = new object();
				
		public bool Enabled {
			get {
				lock(_lockEnabled) {
								
					return _Enabled;
				}
			}
			set {
				lock(_lockEnabled) {
					_Enabled = value;
					
					if(Settings != null)
						Settings.SaveSetting("Authentication.LDAP.Enabled", value.ToString());
				}
			}
		}
		
		// Servers
		private string[] _Servers;
		private object _lockServers = new object();
				
		public string[] Servers {
			get {
				lock(_lockServers) {
								
					return _Servers;
				}
			}
			set {
				lock(_lockServers) {
					_Servers = value;
					
					if(Settings != null)
						Settings.SaveSetting("Authentication.LDAP.Servers", String.Join(",", value));
				}
			}
		}
		
		// Domain
		private string _Domain;
		private object _lockDomain = new object();
				
		public string Domain {
			get {
				lock(_lockDomain) {
								
					return _Domain;
				}
			}
			set {
				lock(_lockDomain) {
					_Domain = value;
					
					if(Settings != null)
						Settings.SaveSetting("Authentication.LDAP.Domain", value);
				}
			}
		}
		
		// Port
		private int? _Port;
		private object _lockPort = new object();
		public const int PortDefault = 389;		
		public int Port {
			get {
				lock(_lockPort) {
					if(_Port == null) return PortDefault;			
					return _Port.Value;
				}
			}
			set {
				lock(_lockPort) {
					_Port = value;
					
					if(Settings != null)
						Settings.SaveSetting("Authentication.LDAP.Port", value.ToString());
				}
			}
		}
				
			private void LoadSettings(Dictionary<string, string> settings) {
								string val = null;
											
			if(settings.TryGetValue("Authentication.LDAP.Enabled", out val)) {
				try {
					_Enabled = bool.Parse(val);
				} catch { } // ignore invalid values
			}
			
						
			if(settings.TryGetValue("Authentication.LDAP.Servers", out val)) {
				try {
					_Servers = val.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
					for(int i = 0; i < _Servers.Length; i++) { _Servers[i] = _Servers[i].Trim(); }
				} catch { } // ignore invalid values
			}
			
						
			if(settings.TryGetValue("Authentication.LDAP.Domain", out val)) {
				try {
					_Domain = val;
				} catch { } // ignore invalid values
			}
			
						
			if(settings.TryGetValue("Authentication.LDAP.Port", out val)) {
				try {
					_Port = int.Parse(val);
				} catch { } // ignore invalid values
			}
			
						}
			
		}
			
			private void LoadSettings(Dictionary<string, string> settings) {
								LDAP = new LDAPSettings(Settings, settings);
			}
			
		}
	
		public EmailSettings Email { get; set; }
		public class EmailSettings {
			protected Settings Settings { get; private set; }
			
			public EmailSettings() { }
			
			public EmailSettings(Settings settings, Dictionary<string, string> loadFrom) {
				Settings = settings;
				LoadSettings(loadFrom);
			}
			
				
		// SendFrom
		private string _SendFrom;
		private object _lockSendFrom = new object();
		public const string SendFromDefault = @"noreply@studystays.com";		
		public string SendFrom {
			get {
				lock(_lockSendFrom) {
					if(_SendFrom == null) return SendFromDefault;			
					return _SendFrom;
				}
			}
			set {
				lock(_lockSendFrom) {
					_SendFrom = value;
					
					if(Settings != null)
						Settings.SaveSetting("Email.SendFrom", value);
				}
			}
		}
		
		public TemplatesSettings Templates { get; set; }
		public class TemplatesSettings {
			protected Settings Settings { get; private set; }
			
			public TemplatesSettings() { }
			
			public TemplatesSettings(Settings settings, Dictionary<string, string> loadFrom) {
				Settings = settings;
				LoadSettings(loadFrom);
			}
			
				
		public UsersSettings Users { get; set; }
		public class UsersSettings {
			protected Settings Settings { get; private set; }
			
			public UsersSettings() { }
			
			public UsersSettings(Settings settings, Dictionary<string, string> loadFrom) {
				Settings = settings;
				LoadSettings(loadFrom);
			}
			
				
		// ResetPassword
		private string _ResetPassword;
		private object _lockResetPassword = new object();
		public const string ResetPasswordDefault = @"Dear [name],

To reset your [sitename] password, please go to this address in your browser:
[resetURL]

Regards,

[sitename] Administration";		
		public string ResetPassword {
			get {
				lock(_lockResetPassword) {
					if(_ResetPassword == null) return ResetPasswordDefault;			
					return _ResetPassword;
				}
			}
			set {
				lock(_lockResetPassword) {
					_ResetPassword = value;
					
					if(Settings != null)
						Settings.SaveSetting("Email.Templates.Users.ResetPassword", value);
				}
			}
		}
				
			private void LoadSettings(Dictionary<string, string> settings) {
								string val = null;
											
			if(settings.TryGetValue("Email.Templates.Users.ResetPassword", out val)) {
				try {
					_ResetPassword = val;
				} catch { } // ignore invalid values
			}
			
						}
			
		}
			
			private void LoadSettings(Dictionary<string, string> settings) {
								Users = new UsersSettings(Settings, settings);
			}
			
		}
			
			private void LoadSettings(Dictionary<string, string> settings) {
								string val = null;
											
			if(settings.TryGetValue("Email.SendFrom", out val)) {
				try {
					_SendFrom = val;
				} catch { } // ignore invalid values
			}
			
			Templates = new TemplatesSettings(Settings, settings);
			}
			
		}
		
		private void LoadSettings() {
			string connStr = ConfigurationManager.ConnectionStrings["AccommodationConnectionString"].ConnectionString;
			
			var conn = new SqlConnection(connStr);
			string sql = "SELECT Name, Value FROM Settings WHERE SiteID = @SiteID";
			
			Dictionary<string, string> settings = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
			conn.Open();
			try {
				var cmd = new SqlCommand(sql, conn);
				cmd.Parameters.AddWithValue("@SiteID", SiteID);
				
				var dr = cmd.ExecuteReader();
				try {
					while(dr.Read()) {
						string name = dr.GetString(0);
						string value = dr.GetString(1);
						
						settings.Add(name, value);
					}
				} finally {
					dr.Close();
				}	
			} finally {
				conn.Close();
			}
			
						
			Appearance = new AppearanceSettings(this, settings);
Authentication = new AuthenticationSettings(this, settings);
Email = new EmailSettings(this, settings);
			
		}
		
		private void SaveSetting(string name, string value) {
			string sql = "IF EXISTS(SELECT Value FROM Settings WHERE SiteID = @SiteID AND Name = @Name) BEGIN " +
				"UPDATE Settings SET Value = @Value WHERE SiteID = @SiteID AND Name = @Name END ELSE BEGIN " +
				"INSERT Settings(SiteID, Name, Value) VALUES(@SiteID, @Name, @Value) END";
			
			if(value == null) {
				sql = "DELETE FROM Settings WHERE SiteID = @SiteID AND Name = @Name";
			}
				
			string connStr = ConfigurationManager.ConnectionStrings["AccommodationConnectionString"].ConnectionString;
			var conn = new SqlConnection(connStr);
			conn.Open();
			try {
				SqlCommand cmd = new SqlCommand(sql, conn);
				cmd.Parameters.AddWithValue("@SiteID", SiteID);
				cmd.Parameters.AddWithValue("@Name", name);
				if(value != null) {
					cmd.Parameters.AddWithValue("@Value", value);
				}
				
				cmd.ExecuteNonQuery();
			} finally {
				conn.Close();
			}
		}
		
	}
}

